package com.generic.mybatis.dal.interceptor.automap;

import com.generic.mybatis.dal.dao.annotation.Exclude;
import com.generic.mybatis.dal.util.OMPException;
import org.apache.ibatis.jdbc.SQL;
import org.apache.ibatis.mapping.ResultMapping;

import javax.persistence.Column;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * 关键字信息
 *
 * @author 关键字信息
 */
public class PkInfo {
    private final Field field;

    private final TableMapper tableMapper;

    private final TableMapper pkTableMapper;

    public PkInfo(TableMapper tableMapper, Field field) {
        this.tableMapper = tableMapper;
        this.field = field;
        pkTableMapper = TableMapperHolder.getTableMapper(field.getType());
        if (pkTableMapper == null) {
            throw new OMPException("can't find mapper for class {}", field.getType().getName());
        }
    }

    public TableMapper getPkTableMapper() {
        return pkTableMapper;
    }

    public TableMapper getTableMapper() {
        return tableMapper;
    }

    public Field getField() {
        return field;
    }

    public SQL buildPkStatement(SQL sql) {
        String template = "%s.%s %s__%s";
        Field[] fields = field.getType().getDeclaredFields();
        for (Field f : fields) {
            //ignore transient, make it like jpa
            if (Modifier.isTransient(f.getModifiers())
                    || f.isAnnotationPresent(Exclude.class)
                    || Modifier.isStatic(f.getModifiers())) {
                continue;
            }

            Annotation[] fieldAnnotations = f.getDeclaredAnnotations();
            Column column = null;
            for (Annotation an : fieldAnnotations) {
                if (an instanceof Column) {
                    column = (Column) an;
                    break;
                }
            }
            if (column != null) {
                String statement = String.format(template, tableMapper.getAlias(), column.name(), tableMapper.getAlias(), column.name());
                sql.SELECT(statement);
            }
        }
        return sql;
    }

    public List<ResultMapping> buildResultMappings() {
        List<ResultMapping> mappings = new ArrayList();
        for (FieldMapper fieldMapper : pkTableMapper.getFieldMapperCache().values()) {
            ResultMapping.Builder builder = new ResultMapping.Builder(getTableMapper().getConfiguration(),
                    String.format("%s.%s", field.getName(), fieldMapper.getFieldName()),
                    String.format("%s__%s", getTableMapper().getAlias(), fieldMapper.getFieldName()), fieldMapper.getField().getType());
            mappings.add(builder.build());
        }
        return mappings;
    }
}
